using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using Acme.BookStore.Domain.Entities;
using Acme.BookStore.Kehus.Dtos;
using Acme.BookStore.Permissions;
using Acme.BookStore.Redis;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Logging;
using StackExchange.Redis;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Caching;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Json;
using Microsoft.Extensions.Configuration;

namespace Acme.BookStore.Kehus
{
    //[Authorize(BookStorePermissions.Kehus.Default)]
    public class KehuAppService : ApplicationService, Acme.BookStore.Kehus.IKehuAppService
    {
        private readonly IKehuRepository _kehuRepository;
        private readonly IDistributedCache _distributedCache;
        private readonly ILogger<KehuAppService> _logger;
        private readonly IJsonSerializer _jsonSerializer;
        private readonly IConfiguration _configuration;
        private readonly int _defaultCacheExpirationSeconds;
        private readonly int _defaultSlidingExpirationSeconds;
        private readonly bool _isRedisCacheEnabled;

        public KehuAppService(
            IKehuRepository kehuRepository,
            IDistributedCache distributedCache,
            ILogger<KehuAppService> logger,
            IJsonSerializer jsonSerializer,
            IConfiguration configuration)
        {
            _kehuRepository = kehuRepository;
            _distributedCache = distributedCache;
            _logger = logger;
            _jsonSerializer = jsonSerializer;
            _configuration = configuration;
            
            // 从配置中读取缓存设置
            _isRedisCacheEnabled = _configuration["Redis:IsEnabled"]?.Equals("true", StringComparison.OrdinalIgnoreCase) == true;
            
            // 从配置中读取默认过期时间，如果没有则使用默认值
            _defaultCacheExpirationSeconds = int.TryParse(_configuration["Redis:DefaultExpirationTime"], out var expTime) 
                ? expTime : 300; // 5分钟默认值
                
            _defaultSlidingExpirationSeconds = int.TryParse(_configuration["Redis:DefaultSlidingExpirationTime"], out var slideTime) 
                ? slideTime : 60; // 1分钟默认滑动过期时间
        }

        public async Task<KehuDto> GetAsync(string id)
        {
            try
            {
                // 如果Redis未启用，直接从数据库获取
                if (!_isRedisCacheEnabled)
                {
                    return await GetFromDatabaseAsync(id);
                }
                
                // 使用新的缓存键管理类获取缓存键
                var cacheKey = KehuCacheKeys.ForKehu(id);
                
                // 尝试从缓存获取数据
                KehuDto? kehuDto = await GetFromCacheAsync<KehuDto>(cacheKey);
                
                // 如果缓存中没有数据，从数据库获取并缓存
                if (kehuDto == null)
                {
                    kehuDto = await GetFromDatabaseAsync(id);
                    
                    // 客户详情数据可以缓存更长时间
                    await SetToCacheAsync(cacheKey, kehuDto, 
                        TimeSpan.FromSeconds(_defaultCacheExpirationSeconds * 2), // 10分钟绝对过期
                        TimeSpan.FromSeconds(_defaultSlidingExpirationSeconds * 2)); // 2分钟滑动过期
                }
                
                return kehuDto;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取客户数据时出错: {Id}", id);
                throw;
            }
        }
        
        private async Task<KehuDto> GetFromDatabaseAsync(string id)
        {
            var kehu = await _kehuRepository.GetAsync(id);
            return ObjectMapper.Map<Kehu, KehuDto>(kehu);
        }

        public async Task<PagedResultDto<KehuDto>> GetListAsync(PagedAndSortedResultRequestDto input)
        {
            try
            {
                // 如果Redis未启用，直接从数据库获取
                if (!_isRedisCacheEnabled)
                {
                    return await GetListFromDatabaseAsync(input);
                }
                
                // 使用新的缓存键管理类获取缓存键
                var cacheKey = KehuCacheKeys.ForKehuList(input.SkipCount, input.MaxResultCount, input.Sorting);
                var countCacheKey = KehuCacheKeys.ForKehuCount();
                
                // 尝试从缓存获取数据
                List<KehuDto>? kehuDtos = await GetFromCacheAsync<List<KehuDto>>(cacheKey);
                
                // 如果缓存中没有数据，从数据库获取并缓存
                if (kehuDtos == null)
                {
                    var kehus = await _kehuRepository.GetListAsync(
                        input.SkipCount,
                        input.MaxResultCount,
                        input.Sorting ?? "Name",
                        string.Empty);

                    kehuDtos = ObjectMapper.Map<List<Kehu>, List<KehuDto>>(kehus) ?? new List<KehuDto>();
                    
                    // 使用统一方法将数据存入缓存
                    await SetToCacheAsync(cacheKey, kehuDtos);
                    
                    // 同时缓存每个客户的详细数据，方便单个查询
                    foreach (var kehuDto in kehuDtos)
                    {
                        if (!string.IsNullOrEmpty(kehuDto.Id))
                        {
                            var singleKehuCacheKey = KehuCacheKeys.ForKehu(kehuDto.Id);
                            await SetToCacheAsync(singleKehuCacheKey, kehuDto,
                                TimeSpan.FromSeconds(_defaultCacheExpirationSeconds * 2),
                                TimeSpan.FromSeconds(_defaultSlidingExpirationSeconds * 2));
                        }
                    }
                }
                
                // 获取总数（先尝试从缓存获取）
                int totalCount = 0;
                var cachedCount = await _distributedCache.GetStringAsync(countCacheKey);
                
                if (string.IsNullOrEmpty(cachedCount))
                {
                    totalCount = (int)await _kehuRepository.GetCountAsync(string.Empty);
                    
                    // 缓存计数结果
                    var cacheOptions = new DistributedCacheEntryOptions
                    {
                        AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(_defaultCacheExpirationSeconds),
                        SlidingExpiration = TimeSpan.FromSeconds(_defaultSlidingExpirationSeconds)
                    };
                    
                    await _distributedCache.SetStringAsync(countCacheKey, totalCount.ToString(), cacheOptions);
                }
                else
                {
                    totalCount = int.Parse(cachedCount);
                }
                
                return new PagedResultDto<KehuDto>(totalCount, kehuDtos);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取客户列表时出错");
                throw;
            }
        }
        
        private async Task<PagedResultDto<KehuDto>> GetListFromDatabaseAsync(PagedAndSortedResultRequestDto input)
        {
            var kehus = await _kehuRepository.GetListAsync(
                input.SkipCount,
                input.MaxResultCount,
                input.Sorting ?? "Name",
                string.Empty);
                
            var kehuDtos = ObjectMapper.Map<List<Kehu>, List<KehuDto>>(kehus) ?? new List<KehuDto>();
            long totalCount = await _kehuRepository.GetCountAsync(string.Empty);
            
            return new PagedResultDto<KehuDto>((int)totalCount, kehuDtos);
        }

        [HttpGet("api/app/kehu/search")]
        public async Task<PagedResultDto<KehuDto>> GetListAsync(KehuSearchDto input)
        {
            try
            {
                // 如果Redis未启用，直接从数据库获取
                if (!_isRedisCacheEnabled)
                {
                    return await GetAdvancedSearchFromDatabaseAsync(input);
                }
                
                // 高级搜索参数
                var filter = input.Filter ?? string.Empty;
                var name = input.Name ?? string.Empty;
                var contactPerson = input.ContactPerson ?? string.Empty;
                var phone = input.Phone ?? string.Empty;
                var mobile = input.Mobile ?? string.Empty;
                var enterpriseAttribute = input.EnterpriseAttribute ?? string.Empty;
                
                // 使用新的缓存键管理类获取缓存键
                var cacheKey = KehuCacheKeys.ForKehuAdvancedSearch(
                    filter, name, contactPerson, phone, mobile, enterpriseAttribute,
                    input.SkipCount, input.MaxResultCount, input.Sorting);
                    
                var countCacheKey = KehuCacheKeys.ForKehuAdvancedSearchCount(
                    filter, name, contactPerson, phone, mobile, enterpriseAttribute);
                
                // 尝试从缓存获取
                List<KehuDto>? kehuDtos = await GetFromCacheAsync<List<KehuDto>>(cacheKey);
                
                // 如果缓存中没有数据，从数据库获取
                if (kehuDtos == null)
                {
                    var kehus = await _kehuRepository.GetListAsync(
                        input.SkipCount,
                        input.MaxResultCount,
                        input.Sorting ?? "Name",
                        filter,
                        name,
                        contactPerson,
                        phone,
                        mobile,
                        enterpriseAttribute
                    );
                    
                    kehuDtos = ObjectMapper.Map<List<Kehu>, List<KehuDto>>(kehus);
                    
                    // 将结果缓存，使用较短的过期时间（高级搜索结果变化较快）
                    await SetToCacheAsync(cacheKey, kehuDtos, 
                        TimeSpan.FromSeconds(_defaultCacheExpirationSeconds / 2),
                        TimeSpan.FromSeconds(_defaultSlidingExpirationSeconds / 2));
                }
                
                // 获取总数（先尝试从缓存获取）
                int totalCount = 0;
                var cachedCount = await _distributedCache.GetStringAsync(countCacheKey);
                
                if (string.IsNullOrEmpty(cachedCount))
                {
                    totalCount = (int)await _kehuRepository.GetCountAsync(
                        filter,
                        name,
                        contactPerson,
                        phone,
                        mobile,
                        enterpriseAttribute
                    );
                    
                    // 缓存计数结果
                    var cacheOptions = new DistributedCacheEntryOptions
                    {
                        AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(_defaultCacheExpirationSeconds / 2),
                        SlidingExpiration = TimeSpan.FromSeconds(_defaultSlidingExpirationSeconds / 2)
                    };
                    
                    await _distributedCache.SetStringAsync(countCacheKey, totalCount.ToString(), cacheOptions);
                }
                else
                {
                    totalCount = int.Parse(cachedCount);
                }
                
                return new PagedResultDto<KehuDto>(totalCount, kehuDtos);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "高级搜索方法出错");
                throw;
            }
        }
        
        private async Task<PagedResultDto<KehuDto>> GetAdvancedSearchFromDatabaseAsync(KehuSearchDto input)
        {
            var filter = input.Filter ?? string.Empty;
            var name = input.Name ?? string.Empty;
            var contactPerson = input.ContactPerson ?? string.Empty;
            var phone = input.Phone ?? string.Empty;
            var mobile = input.Mobile ?? string.Empty;
            var enterpriseAttribute = input.EnterpriseAttribute ?? string.Empty;
            
            var kehus = await _kehuRepository.GetListAsync(
                input.SkipCount,
                input.MaxResultCount,
                input.Sorting ?? "Name",
                filter,
                name,
                contactPerson,
                phone,
                mobile,
                enterpriseAttribute
            );
            
            var kehuDtos = ObjectMapper.Map<List<Kehu>, List<KehuDto>>(kehus);
            
            var totalCount = await _kehuRepository.GetCountAsync(
                filter,
                name,
                contactPerson,
                phone,
                mobile,
                enterpriseAttribute
            );
            
            return new PagedResultDto<KehuDto>((int)totalCount, kehuDtos);
        }
        
        [HttpGet("api/app/kehu/search-by-name")]
        public async Task<PagedResultDto<KehuDto>> SearchByNameAsync(KehuNameSearchDto input)
        {
            try
            {
                // 如果Redis未启用，直接从数据库获取
                if (!_isRedisCacheEnabled)
                {
                    return await SearchByNameFromDatabaseAsync(input);
                }
                
                var nameKeyword = input.NameKeyword ?? string.Empty;
                
                // 使用新的缓存键管理类获取缓存键
                var cacheKey = KehuCacheKeys.ForKehuNameSearch(nameKeyword, input.SkipCount, input.MaxResultCount, input.Sorting);
                var countCacheKey = KehuCacheKeys.ForKehuNameSearchCount(nameKeyword);
                
                // 尝试从缓存获取
                List<KehuDto>? kehuDtos = await GetFromCacheAsync<List<KehuDto>>(cacheKey);
                
                // 如果缓存中没有数据，从数据库获取
                if (kehuDtos == null)
                {
                    var kehus = await _kehuRepository.SearchByNameAsync(
                        input.SkipCount,
                        input.MaxResultCount,
                        input.Sorting ?? "Name",
                        nameKeyword
                    );
                    
                    kehuDtos = ObjectMapper.Map<List<Kehu>, List<KehuDto>>(kehus);
                    
                    // 将结果缓存
                    await SetToCacheAsync(cacheKey, kehuDtos);
                }
                
                // 获取总数（先尝试从缓存获取）
                int totalCount = 0;
                var cachedCount = await _distributedCache.GetStringAsync(countCacheKey);
                
                if (string.IsNullOrEmpty(cachedCount))
                {
                    totalCount = (int)await _kehuRepository.GetCountByNameAsync(nameKeyword);
                    
                    // 缓存计数结果
                    var cacheOptions = new DistributedCacheEntryOptions
                    {
                        AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(_defaultCacheExpirationSeconds),
                        SlidingExpiration = TimeSpan.FromSeconds(_defaultSlidingExpirationSeconds)
                    };
                    
                    await _distributedCache.SetStringAsync(countCacheKey, totalCount.ToString(), cacheOptions);
                }
                else
                {
                    totalCount = int.Parse(cachedCount);
                }
                
                return new PagedResultDto<KehuDto>(totalCount, kehuDtos);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "按名称搜索客户出错");
                throw;
            }
        }
        
        private async Task<PagedResultDto<KehuDto>> SearchByNameFromDatabaseAsync(KehuNameSearchDto input)
        {
            var nameKeyword = input.NameKeyword ?? string.Empty;
            
            var kehus = await _kehuRepository.SearchByNameAsync(
                input.SkipCount,
                input.MaxResultCount,
                input.Sorting ?? "Name",
                nameKeyword
            );
            
            var kehuDtos = ObjectMapper.Map<List<Kehu>, List<KehuDto>>(kehus);
            long totalCount = await _kehuRepository.GetCountByNameAsync(nameKeyword);
            
            return new PagedResultDto<KehuDto>((int)totalCount, kehuDtos);
        }

        //[Authorize(BookStorePermissions.Kehus.Create)]
        public async Task<KehuDto> CreateAsync(CreateKehuDto input)
        {
            // 使用GUID作为客户编码
            var id = Guid.NewGuid().ToString("N");
            
            // 使用构造函数创建实体
            var kehu = new Kehu(id)
            {
                Name = input.Name,
                Address = input.Address,
                ContactPerson = input.ContactPerson,
                Phone = input.Phone,
                Mobile = input.Mobile,
                Contact1 = input.Contact1,
                EnterpriseAttribute = input.EnterpriseAttribute,
                ContractNumber = input.ContractNumber,
                Phone1 = input.Phone1,
                EmailAddress = input.EmailAddress,
                Remarks = input.Remarks
            };

            await _kehuRepository.InsertAsync(kehu);
            
            // 清除缓存
            await RemoveKehuListCacheAsync();

            return ObjectMapper.Map<Kehu, KehuDto>(kehu);
        }

        //[Authorize(BookStorePermissions.Kehus.Edit)]
        public async Task<KehuDto> UpdateAsync(string id, CreateKehuDto input)
        {
            var kehu = await _kehuRepository.GetAsync(id);

            kehu.Name = input.Name;
            kehu.Address = input.Address;
            kehu.ContactPerson = input.ContactPerson;
            kehu.Phone = input.Phone;
            kehu.Mobile = input.Mobile;
            kehu.Contact1 = input.Contact1;
            kehu.EnterpriseAttribute = input.EnterpriseAttribute;
            kehu.ContractNumber = input.ContractNumber;
            kehu.Phone1 = input.Phone1;
            kehu.EmailAddress = input.EmailAddress;
            kehu.Remarks = input.Remarks;

            await _kehuRepository.UpdateAsync(kehu);
            
            // 清除缓存
            await RemoveKehuListCacheAsync();
            
            // 同时清除单个客户的缓存
            if (_isRedisCacheEnabled)
            {
                var kehuCacheKey = KehuCacheKeys.ForKehu(id);
                await _distributedCache.RemoveAsync(kehuCacheKey);
            }

            return ObjectMapper.Map<Kehu, KehuDto>(kehu);
        }

        //[Authorize(BookStorePermissions.Kehus.Delete)]
        public async Task DeleteAsync(string id)
        {
            await _kehuRepository.DeleteAsync(id);
            
            // 清除缓存
            await RemoveKehuListCacheAsync();
            
            // 同时清除单个客户的缓存
            if (_isRedisCacheEnabled)
            {
                var kehuCacheKey = KehuCacheKeys.ForKehu(id);
                await _distributedCache.RemoveAsync(kehuCacheKey);
            }
        }
        
        // 通用缓存获取方法
        private async Task<T?> GetFromCacheAsync<T>(string cacheKey) where T : class
        {
            try
            {
                var cachedData = await _distributedCache.GetStringAsync(cacheKey);
                if (!string.IsNullOrEmpty(cachedData))
                {
                    var result = _jsonSerializer.Deserialize<T>(cachedData);
                    _logger.LogDebug("从缓存获取数据: {CacheKey}", cacheKey);
                    return result;
                }
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "获取或解析缓存数据失败: {CacheKey}", cacheKey);
            }
            
            return null;
        }
        
        // 通用缓存设置方法
        private async Task SetToCacheAsync<T>(string cacheKey, T data, 
            TimeSpan? absoluteExpiration = null, TimeSpan? slidingExpiration = null) where T : class
        {
            if (data == null)
                return;
                
            try
            {
                var serializedData = _jsonSerializer.Serialize(data);
                if (!string.IsNullOrEmpty(serializedData))
                {
                    var cacheOptions = new DistributedCacheEntryOptions
                    {
                        AbsoluteExpirationRelativeToNow = absoluteExpiration ?? TimeSpan.FromSeconds(_defaultCacheExpirationSeconds),
                        SlidingExpiration = slidingExpiration ?? TimeSpan.FromSeconds(_defaultSlidingExpirationSeconds)
                    };
                    
                    await _distributedCache.SetStringAsync(cacheKey, serializedData, cacheOptions);
                    _logger.LogDebug("数据已缓存: {CacheKey}", cacheKey);
                }
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "缓存数据失败: {CacheKey}", cacheKey);
            }
        }
        
        // 智能缓存清除：使用模式匹配而非单个键删除
        private async Task RemoveKehuListCacheAsync()
        {
            if (!_isRedisCacheEnabled)
                return;
                
            try
            {
                // 获取Redis连接配置
                var redisConfig = _configuration["Redis:Configuration"] ?? "localhost:6379";
                
                // 使用Redis命令清除缓存，更高效的模式匹配删除
                var connection = await ConnectionMultiplexer.ConnectAsync(redisConfig);
                var server = connection.GetServer(connection.GetEndPoints().First());
                var database = connection.GetDatabase();
                
                // 需要清除的缓存模式
                var patterns = new[]
                {
                    "BookStore:Kehu:list:*",
                    "BookStore:Kehu:nameSearch:*",
                    "BookStore:Kehu:advSearch:*",
                    "BookStore:Kehu:count"
                };
                
                foreach (var pattern in patterns)
                {
                    try
                    {
                        var keys = server.Keys(pattern: pattern).ToArray();
                        if (keys.Length > 0)
                        {
                            await database.KeyDeleteAsync(keys);
                            _logger.LogInformation("已清除{Count}个{Pattern}相关的缓存键", keys.Length, pattern);
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogWarning(ex, "使用模式{Pattern}清除缓存时出错", pattern);
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "清除客户列表缓存时出错");
            }
        }
    }
} 